﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Collections.ObjectModel;
using System.Device.Location;
using MolfMolfMolf.ServiceReference1;
using Microsoft.Phone.Controls.Maps;
using System.Windows.Media.Imaging;
using Microsoft.Phone.Shell;
using Microsoft.Phone.Tasks;

namespace MolfMolfMolf
{
    public partial class MapResultPage : PhoneApplicationPage
    {
        private string location = String.Empty;
        private bool isCurrent;

        private ObservableCollection<GeoCoordinate> pins;
        private Pushpin centerPin;
        private GeocodeServiceClient gsc;
        private GeocodeRequest grq;
        private ReverseGeocodeRequest rgrq;
        private GeoCoordinateWatcher watcher;
        private GeoCoordinate centerLocation;

        public MapResultPage()
        {
            InitializeComponent();

            //instantiation
            pins = new ObservableCollection<GeoCoordinate>();
            centerPin = new Pushpin();
            gsc = new GeocodeServiceClient("BasicHttpBinding_IGeocodeService");
            grq = new GeocodeRequest();
            rgrq = new ReverseGeocodeRequest();
            watcher = new GeoCoordinateWatcher();
            centerPin.Style = (Style)App.Current.Resources["PushpinCurrentStyle"];

            //set credential
            grq.Credentials = new Microsoft.Phone.Controls.Maps.Credentials()
            {
                ApplicationId = "AllcyjAOBx9lzjNqljybck3_sP-BdIZUt9EhcbW4ZCsLHmV6w4mqTihselBY7EL6"
            };
            rgrq.Credentials = new Microsoft.Phone.Controls.Maps.Credentials()
            {
                ApplicationId = "AllcyjAOBx9lzjNqljybck3_sP-BdIZUt9EhcbW4ZCsLHmV6w4mqTihselBY7EL6"
            };

            //hook handling functions
            gsc.GeocodeCompleted += new EventHandler<GeocodeCompletedEventArgs>(gsc_GeocodeCompleted);
            gsc.ReverseGeocodeCompleted += new EventHandler<ReverseGeocodeCompletedEventArgs>(gsc_ReverseGeocodeCompleted);
        }
        

        void gsc_ReverseGeocodeCompleted(object sender, ReverseGeocodeCompletedEventArgs e)
        {
            PageTitle.Text = e.Result.Results[0].DisplayName;
            PageTitle.TextWrapping = TextWrapping.Wrap;
        }

        void gsc_GeocodeCompleted(object sender, GeocodeCompletedEventArgs e)
        {
            //get geo info
            centerLocation = e.Result.Results[0].Locations[0];

            //set map rectangle in a proper zoom in level
            ClubMap.Center = centerLocation;
            ClubMap.ZoomLevel = 9;

            //set title
            PageTitle.Text = e.Result.Results[0].Address.FormattedAddress;
            PageTitle.TextWrapping = TextWrapping.Wrap;

            pushClubPins();
        }

        private void pushClubPins()
        {
            //club pushpins
            ObservableCollection<Club> clubs = ((App)(App.Current)).clubs;
            Random rand = new Random();
            int i = 1;
            foreach (Club club in clubs)
            {

                Pushpin newPin = new Pushpin();
                newPin.Content = i.ToString();
                newPin.Style = (Style)App.Current.Resources["PushpinCurrentStyle"];
                //double newLatitude = centerLocation.Latitude + ((double)rand.Next(-5, 5)) / (double)20;
                //double newLongitude = centerLocation.Longitude + ((double)rand.Next(-5, 5)) / (double)10;
                //GeoCoordinate newLocation = new GeoCoordinate(newLatitude, newLongitude);
                GeoCoordinate newLocation = club.ClubCoordinate;
                //club.ClubCoordinate = newLocation;
                newPin.Location = newLocation;
                ClubMap.Children.Add(newPin);
                newPin.Tap += new EventHandler<GestureEventArgs>(newPin_Tap);
                i++;
            }

        }

        void newPin_Tap(object sender, GestureEventArgs e)
        {
            int index = Convert.ToInt32(((Pushpin)sender).Content);
            ObservableCollection<Club> clubs = ((App)(App.Current)).clubs;
            PhoneApplicationService.Current.State["club"] = clubs[index - 1];
            NavigationService.Navigate(new Uri("/ResultDetailPage.xaml", UriKind.Relative));
        }

        void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
        {
            ClubMap.Children.Remove(centerPin);
            centerPin.Location = watcher.Position.Location;
            ClubMap.Children.Add(centerPin);

            //set map rectangle in a proper zoom in level
            ClubMap.Center = watcher.Position.Location;

            //set location title
            rgrq.Location = watcher.Position.Location;
            gsc.ReverseGeocodeAsync(rgrq);
        }

        protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedFrom(e);
            watcher.Stop();
        }

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
            if (e.NavigationMode == System.Windows.Navigation.NavigationMode.Forward
                || e.NavigationMode == System.Windows.Navigation.NavigationMode.New)
            {
                if (!NavigationContext.QueryString.TryGetValue("location", out location))
                {
                    MessageBox.Show("Error: fail to navigate");
                    return;
                }
                isCurrent = (location == "current");
                ClubMap.Children.Clear();

                if (isCurrent)//get current location, set pushpin for it
                {
                    //get geo info
                    watcher.Start();//.TryStart(false, TimeSpan.FromMilliseconds(1000));
                    watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged);
                    centerLocation = watcher.Position.Location;

                    //add pushpin
                    centerPin.Location = centerLocation;
                    ClubMap.Children.Add(centerPin);

                    //set map rectangle in a proper zoom in level
                    ClubMap.Center = centerLocation;
                    ClubMap.ZoomLevel = 9;

                    //set location title
                    rgrq.Location = centerLocation;
                    try
                    {
                        gsc.ReverseGeocodeAsync(rgrq);
                    }
                    catch (Exception ex)
                    {
                    }
                }
                else
                {
                    grq.Query = location;
                    gsc.GeocodeAsync(grq);
                    return;
                }

                pushClubPins();
            }
        }
    }
}